`timescale 1ns/1ns
`include "../../tb/eSPI_Harness.sv"
module eSPI_TestBench();

initial #130_000_000 $finish;

/******************************************************************
	Verification
*******************************************************************/
class channel_model;
	task peripheral_channel();
	endtask

	task virtual_wire_channel();
	endtask

	task oob_channel();
	endtask

	task flash_channel();
	endtask

	task all_channel();
		peripheral_channel();
		virtual_wire_channel();
		oob_channel();
		flash_channel();
	endtask
endclass

class IO_model;
	espi_single p1 = new();
	espi_dual p2 = new();
	espi_quad p3 = new();
	int cycle = 25;
	function new();
	endfunction
	task signal_model();
		p1.espi_reset();
		p1.eSPI_signal_initial(cycle);
		//Peripheral channel
		`ifdef Peripheral
		
		p1.eSPI_peripheral_initial(cycle);
		p1.get_configuration_randc(cycle);
	
		p1.get_status(cycle);
		p1.put_pc_randc(cycle);
		p1.put_np_randc(cycle);
		p1.get_pc_randc(cycle);
		p1.get_np_randc(cycle);

		p1.put_short_randc(cycle);
	
		p1.peripheral_protocal_error(cycle);
		p1.peripheral_unsupported_command(cycle);
		p1.peripheral_unsupported_cycle(cycle);
		p1.invalid_command_error(cycle);
		p1.invalid_cycle_error(cycle);
		p1.peripheral_crc_error(cycle);
		`endif

		`ifdef Virtual_wire
		//Virtual Wire channel
		p1.eSPI_vwire_initial(cycle);
		p1.put_vwire_randc(cycle);
		p1.get_vwire_randc(cycle);
		p1.invalid_command_error(cycle);
		`endif
		
		`ifdef OOB
		//oob channel
		p1.eSPI_oob_initial(cycle);
		p1.put_oob_randc(cycle);
		p1.get_oob_randc(cycle);
		`endif

		//flash channel
		`ifdef flash
		p1.eSPI_flash_initial(cycle);
		p1.get_configuration_randc(cycle);
		p1.get_status(cycle);

		p1.put_flash_c_randc(cycle);
		p1.put_flash_np_randc(cycle);
		p1.get_flash_c_randc(cycle);
		p1.get_flash_np_randc(cycle);

		p1.invalid_command_error(cycle);
		p1.invalid_cycle_error(cycle);
		`endif

		//all channel
		`ifdef all_channel
			p1.eSPI_peripheral_initial(cycle);
			p1.get_configuration_randc(cycle);
	
			p1.get_status(cycle);
			p1.put_pc_randc(cycle);
			p1.put_np_randc(cycle);
			p1.get_pc_randc(cycle);
			p1.get_np_randc(cycle);

			p1.put_short_randc(cycle);
	
			p1.peripheral_protocal_error(cycle);
			p1.peripheral_unsupported_command(cycle);
			p1.peripheral_unsupported_cycle(cycle);
			p1.invalid_command_error(cycle);
			p1.invalid_cycle_error(cycle);
			p1.peripheral_crc_error(cycle);

			p1.eSPI_vwire_initial(cycle);
			p1.put_vwire_randc(cycle);
			p1.get_vwire_randc(cycle);
			p1.invalid_command_error(cycle);

			p1.eSPI_oob_initial(cycle);
			p1.put_oob_randc(cycle);
			p1.get_oob_randc(cycle);

			p1.eSPI_flash_initial(cycle);
			p1.get_configuration_randc(cycle);
			p1.get_status(cycle);

			p1.put_flash_c_randc(cycle);
			p1.put_flash_np_randc(cycle);
			p1.get_flash_c_randc(cycle);
			p1.get_flash_np_randc(cycle);

			p1.invalid_command_error(cycle);
			p1.invalid_cycle_error(cycle);
		`endif
	endtask

	task dual_model();
		p2.espi_reset();
		p2.eSPI_signal_initial(cycle);
		//Peripheral channel
		`ifdef Peripheral
		
			p2.eSPI_peripheral_initial(cycle);
			p2.get_configuration_randc(cycle);
	
			p2.get_status(cycle);
			p2.put_pc_randc(cycle);
			p2.put_np_randc(cycle);
			p2.get_pc_randc(cycle);
			p2.get_np_randc(cycle);

			p2.put_short_randc(cycle);
	
			p2.peripheral_protocal_error(cycle);
			p2.peripheral_unsupported_command(cycle);
			p2.peripheral_unsupported_cycle(cycle);
			p2.invalid_command_error(cycle);
			p2.invalid_cycle_error(cycle);
			p2.peripheral_crc_error(cycle);
		`endif

		`ifdef Virtual_wire
		//Virtual Wire channel
			p2.eSPI_vwire_initial(cycle);
			p2.put_vwire_randc(cycle);
			p2.get_vwire_randc(cycle);
			p2.invalid_command_error(cycle);
		`endif
		
		`ifdef OOB
		//oob channel
			p2.eSPI_oob_initial(cycle);
			p2.put_oob_randc(cycle);
			p2.get_oob_randc(cycle);
		`endif

		//flash channel
		`ifdef flash
			p2.eSPI_flash_initial(cycle);
			p2.get_configuration_randc(cycle);
			p2.get_status(cycle);

			p2.put_flash_c_randc(cycle);
			p2.put_flash_np_randc(cycle);
			p2.get_flash_c_randc(cycle);
			p2.get_flash_np_randc(cycle);

			p2.invalid_command_error(cycle);
			p2.invalid_cycle_error(cycle);
		`endif

		//all channel
		`ifdef all_channel
			p2.eSPI_peripheral_initial(cycle);
			p2.get_configuration_randc(cycle);
	
			p2.get_status(cycle);
			p2.put_pc_randc(cycle);
			p2.put_np_randc(cycle);
			p2.get_pc_randc(cycle);
			p2.get_np_randc(cycle);

			p2.put_short_randc(cycle);
	
			p2.peripheral_protocal_error(cycle);
			p2.peripheral_unsupported_command(cycle);
			p2.peripheral_unsupported_cycle(cycle);
			p2.invalid_command_error(cycle);
			p2.invalid_cycle_error(cycle);
			p2.peripheral_crc_error(cycle);

			p2.eSPI_vwire_initial(cycle);
			p2.put_vwire_randc(cycle);
			p2.get_vwire_randc(cycle);
			p2.invalid_command_error(cycle);

			p2.eSPI_oob_initial(cycle);
			p2.put_oob_randc(cycle);
			p2.get_oob_randc(cycle);

			p2.eSPI_flash_initial(cycle);
			p2.get_configuration_randc(cycle);
			p2.get_status(cycle);

			p2.put_flash_c_randc(cycle);
			p2.put_flash_np_randc(cycle);
			p2.get_flash_c_randc(cycle);
			p2.get_flash_np_randc(cycle);

			p2.invalid_command_error(cycle);
			p2.invalid_cycle_error(cycle);
		`endif
	endtask

	task quad_model();
		p3.espi_reset();
		p3.eSPI_signal_initial(cycle);
		/*
		//Peripheral channel
		`ifdef Peripheral
		
			p3.eSPI_peripheral_initial(cycle);
			p3.get_configuration_randc(cycle);
	
			p3.get_status(cycle);
			p3.put_pc_randc(cycle);
			p3.put_np_randc(cycle);
			p3.get_pc_randc(cycle);
			p3.get_np_randc(cycle);

			p3.put_short_randc(cycle);
	
			p3.peripheral_protocal_error(cycle);
			p3.peripheral_unsupported_command(cycle);
			p3.peripheral_unsupported_cycle(cycle);
			p3.invalid_command_error(cycle);
			p3.invalid_cycle_error(cycle);
			p3.peripheral_crc_error(cycle);
		`endif
		*/
		`ifdef Virtual_wire
		//Virtual Wire channel
			p3.eSPI_vwire_initial(cycle);
			p3.put_vwire_randc(cycle);
			p3.get_vwire_randc(cycle);
			p3.invalid_command_error(cycle);
		`endif
		
		`ifdef OOB
		//oob channel
			p3.eSPI_oob_initial(cycle);
			p3.put_oob_randc(cycle);
			p3.get_oob_randc(cycle);
		`endif

		//flash channel
		`ifdef flash
			p3.eSPI_flash_initial(cycle);
			p3.get_configuration_randc(cycle);
			p3.get_status(cycle);

			p3.put_flash_c_randc(cycle);
			p3.put_flash_np_randc(cycle);
			p3.get_flash_c_randc(cycle);
			p3.get_flash_np_randc(cycle);

			p3.invalid_command_error(cycle);
			p3.invalid_cycle_error(cycle);
		`endif

		//all channel
		`ifdef all_channel
			p3.eSPI_peripheral_initial(cycle);
			p3.get_configuration_randc(cycle);
	
			p3.get_status(cycle);
			p3.put_pc_randc(cycle);
			p3.put_np_randc(cycle);
			p3.get_pc_randc(cycle);
			p3.get_np_randc(cycle);

			p3.put_short_randc(cycle);
	
			p3.peripheral_protocal_error(cycle);
			p3.peripheral_unsupported_command(cycle);
			p3.peripheral_unsupported_cycle(cycle);
			p3.invalid_command_error(cycle);
			p3.invalid_cycle_error(cycle);
			p3.peripheral_crc_error(cycle);

			p3.eSPI_vwire_initial(cycle);
			p3.put_vwire_randc(cycle);
			p3.get_vwire_randc(cycle);
			p3.invalid_command_error(cycle);

			p3.eSPI_oob_initial(cycle);
			p3.put_oob_randc(cycle);
			p3.get_oob_randc(cycle);

			p3.eSPI_flash_initial(cycle);
			p3.get_configuration_randc(cycle);
			p3.get_status(cycle);

			p3.put_flash_c_randc(cycle);
			p3.put_flash_np_randc(cycle);
			p3.get_flash_c_randc(cycle);
			p3.get_flash_np_randc(cycle);

			p3.invalid_command_error(cycle);
			p3.invalid_cycle_error(cycle);
		`endif
	endtask

	task all_model();
	//p1.get_status(cycle);
		p1.espi_reset();
	`ifdef PERIPHERAL
		p1.eSPI_signal_initial(cycle);

		p1.eSPI_peripheral_initial(cycle);

		p1.get_configuration_randc(cycle);
	
		p1.get_status(cycle);
		p1.put_pc_randc(cycle);
		p1.put_np_randc(cycle);
		p1.get_pc_randc(cycle);
		p1.get_np_randc(cycle);
		p1.put_short_randc(cycle);
		//error 
	/*	p1.invalid_command_error(cycle);
		p1.invalid_cycle_error(cycle);
		p1.peripheral_crc_error(cycle);
		p1.peripheral_protocal_error(cycle);
		p1.peripheral_malforned_packet(cycle);
		p1.peripheral_unsupported_command(cycle);
		p1.peripheral_unsupported_cycle(cycle);
		p1.peripheral_unsupported_message(cycle);
		p1.peripheral_unsupported_length(cycle);*/
	`endif
	`ifdef VIRTUAL_WIRE
		p1.eSPI_vwire_initial(cycle);
		p1.put_vwire_randc(cycle);
		p1.get_vwire_randc(cycle);
	`endif
	`ifdef OOB
		p1.eSPI_oob_initial(cycle);
		p1.put_oob_randc(cycle);
		p1.get_oob_randc(cycle);
	`endif
	`ifdef FLASH
		p1.eSPI_flash_initial(cycle);
		p1.get_configuration_randc(cycle);
		p1.get_status(cycle);
	
		p1.put_flash_c_randc(cycle);
		p1.put_flash_np_randc(cycle);
		p1.get_flash_c_randc(cycle);
		p1.get_flash_np_randc(cycle);
	`endif
	`ifdef ALL_CHANNEL
		p1.eSPI_signal_initial(cycle);

		p1.eSPI_peripheral_initial(cycle);

		p1.get_configuration_randc(cycle);
	
		p1.get_status(cycle);
		p1.put_pc_randc(cycle);
		p1.put_np_randc(cycle);
		p1.get_pc_randc(cycle);
		p1.get_np_randc(cycle);
		p1.put_short_randc(cycle);
/*		p1.put_vwire_randc(cycle);

		p1.invalid_command_error(cycle);
		p1.invalid_cycle_error(cycle);
		p1.peripheral_crc_error(cycle);
		p1.peripheral_protocal_error(cycle);
		p1.peripheral_malforned_packet(cycle);
		p1.peripheral_unsupported_command(cycle);
		p1.peripheral_unsupported_cycle(cycle);
		p1.peripheral_unsupported_message(cycle);
		p1.peripheral_unsupported_length(cycle);
*/
		p1.eSPI_vwire_initial(cycle);
		p1.put_vwire_randc(cycle);
		p1.get_vwire_randc(cycle);

		p1.eSPI_oob_initial(cycle);
		p1.put_oob_randc(cycle);
		p1.get_oob_randc(cycle);

		p1.eSPI_flash_initial(cycle);
		p1.get_configuration_randc(cycle);
		p1.get_status(cycle);
	
		p1.put_flash_c_randc(cycle);
		p1.put_flash_np_randc(cycle);
		p1.get_flash_c_randc(cycle);
		p1.get_flash_np_randc(cycle);

		p1.eSPI_dual_initial(cycle);
		
		p2.eSPI_peripheral_initial(cycle);
		p2.get_configuration_randc(cycle);
	
		p2.get_status(cycle);
		p2.put_pc_randc(cycle);
		p2.put_np_randc(cycle);
		p2.get_pc_randc(cycle);
		p2.get_np_randc(cycle);

		p2.put_short_randc(cycle);

		p2.eSPI_vwire_initial(cycle);
		p2.put_vwire_randc(cycle);
		p2.get_vwire_randc(cycle);

		p2.eSPI_oob_initial(cycle);
		p2.put_oob_randc(cycle);
		p2.get_oob_randc(cycle);

		p2.eSPI_flash_initial(cycle);
		p2.get_configuration_randc(cycle);
		p2.get_status(cycle);

		p2.put_flash_c_randc(cycle);
		p2.put_flash_np_randc(cycle);
		p2.get_flash_c_randc(cycle);
		p2.get_flash_np_randc(cycle);

		p2.eSPI_quad_initial(cycle);

		p3.eSPI_peripheral_initial(cycle);
		p3.get_configuration_randc(cycle);
	
		p3.get_status(cycle);
		p3.put_pc_randc(cycle);
		p3.put_np_randc(cycle);
		p3.get_pc_randc(cycle);
		p3.get_np_randc(cycle);

		p3.put_short_randc(cycle);
	`endif
/*
		p1.eSPI_dual_initial(cycle);
		
		p2.eSPI_peripheral_initial(cycle);
		p2.get_configuration_randc(cycle);
	
		p2.get_status(cycle);
		p2.put_pc_randc(cycle);
		p2.put_np_randc(cycle);
		p2.get_pc_randc(cycle);
		p2.get_np_randc(cycle);

		p2.put_short_randc(cycle);	

		//error 
		p2.invalid_command_error(cycle);
		p2.invalid_cycle_error(cycle);
		p2.peripheral_crc_error(cycle);
		p2.peripheral_protocal_error(cycle);
		p2.peripheral_unsupported_command(cycle);
		p2.peripheral_unsupported_cycle(cycle);
		p2.peripheral_unsupported_message(cycle);
*//*
		p2.eSPI_vwire_initial(cycle);
		p2.put_vwire_randc(cycle);
		p2.get_vwire_randc(cycle);

		p2.eSPI_oob_initial(cycle);
		p2.put_oob_randc(cycle);
		p2.get_oob_randc(cycle);

		p2.eSPI_flash_initial(cycle);
		p2.get_configuration_randc(cycle);
		p2.get_status(cycle);

		p2.put_flash_c_randc(cycle);
		p2.put_flash_np_randc(cycle);
		p2.get_flash_c_randc(cycle);
		p2.get_flash_np_randc(cycle);

		p2.eSPI_quad_initial(cycle);

		p3.eSPI_peripheral_initial(cycle);
		p3.get_configuration_randc(cycle);
	
		p3.get_status(cycle);
		p3.put_pc_randc(cycle);
		p3.put_np_randc(cycle);
		p3.get_pc_randc(cycle);
		p3.get_np_randc(cycle);

		p3.put_short_randc(cycle);
		*/
/*
		//error 
		p3.invalid_command_error(cycle);
		p3.invalid_cycle_error(cycle);
		p3.peripheral_crc_error(cycle);
		p3.peripheral_protocal_error(cycle);
		p3.peripheral_unsupported_command(cycle);
		p3.peripheral_unsupported_cycle(cycle);
		p3.peripheral_unsupported_message(cycle);
*/
/*
		p3.eSPI_vwire_initial(cycle);
		p3.put_vwire_randc(cycle);
		p3.get_vwire_randc(cycle);

		p3.eSPI_oob_initial(cycle);
		p3.put_oob_randc(cycle);
		p3.get_oob_randc(cycle);

		p3.eSPI_flash_initial(cycle);
		p3.get_configuration_randc(cycle);
		p3.get_status(cycle);

		p3.put_flash_c_randc(cycle);
		p3.put_flash_np_randc(cycle);
		p3.get_flash_c_randc(cycle);
		p3.get_flash_np_randc(cycle);

		p3.eSPI_signal_initial(cycle);

		p1.eSPI_signal_initial(cycle);
*/
	endtask
endclass

initial
begin
	IO_model p1 = new();
	
	system_reset();
	#100ns;
	`ifdef MODEL_SINGLE
		p1.signal_model();
	`endif
	`ifdef MODEL_DUAL 
		p1.dual_model();
	`endif
	`ifdef MODEL_QUAD
		p1.quad_model();
	`endif
	`ifdef MODEL_ALL
		p1.all_model();
	`endif
end


endmodule 
